<template>
    <el-row class="gpt_box" >
        <el-col class="historys" :span="5">
            <div class="new_chat_btn" @click="newChat">
                <i class="el-icon-plus"></i>创建新聊天
            </div>
            <!-- <span class="title">历史记录</span> -->
            <div class="history_btn_box" v-loading="historyLoading" element-loading-text="正在拉取历史记录..." element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.8)">
                <div v-for="(history, index) in historys" :key="index" :class="history.uuid == thisHistoryId ? 'hixtory_btn this_history' : 'hixtory_btn'" @click="chengeHistory(history.uuid)">
                    <div class="history_name">
                        <i class="el-icon-chat-dot-square"></i>{{ history.historyName }}
                    </div>
                    <div class="total_tokens">
                        总消耗：{{ history.totalTokens || 0 }} tokens
                    </div>
                </div>
            </div>
        </el-col>
        <el-col class="chat" :span="19" v-loading="chatLoading" :element-loading-text="chatLoadingText" element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.8)">
            <div class="messages" ref="messages">
                <!-- 提示 -->
                <div class="message" v-if="messages.length == 0">
                    <el-row class="bot">
                        <el-col :span="1" class="bot_head">
                            <svg t="1683273862076" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2681">
                                <path d="M501.8 121.6h20.4v128h-20.4z" fill="#A0ABBD" p-id="2682"></path>
                                <path d="M512 873.5H226.5c-32.6 0-59.1-26.4-59.1-59.1V285.7c0-32.6 26.4-59.1 59.1-59.1H512v646.9z" fill="#6484BF" p-id="2683"></path>
                                <path d="M512 226.7h285.5c32.6 0 59.1 26.4 59.1 59.1v528.7c0 32.6-26.4 59.1-59.1 59.1H512V226.7z" fill="#4C6FAF" p-id="2684"></path>
                                <path d="M640.1 448.2m-59.1 0a59.1 59.1 0 1 0 118.2 0 59.1 59.1 0 1 0-118.2 0Z" fill="#FFFFFF" p-id="2685"></path>
                                <path d="M384.1 448.2m-59.1 0a59.1 59.1 0 1 0 118.2 0 59.1 59.1 0 1 0-118.2 0Z" fill="#FFFFFF" p-id="2686"></path>
                                <path d="M512 113.2m-49 0a49 49 0 1 0 98 0 49 49 0 1 0-98 0Z" fill="#A0ABBD" p-id="2687"></path>
                                <path d="M167.6 615.6l-54.4-27.2V458.1l54.4-29.2zM856.4 427.9l54.4 27.3v130.2l-54.4 29.2z" fill="#39507A" p-id="2688"></path>
                            </svg>
                        </el-col>
                        <el-col :span="22" class="bot_content">
                            <mavon-editor class="bot_content_span"
                                v-model="tips"
                                :subfield="false" 
                                :defaultOpen="'preview'" 
                                :toolbarsFlag="false" 
                                :editable="false"/>
                        </el-col>
                    </el-row>
                </div>
                <!-- 正文 -->
                <div class="message" v-for="(message, index) in messages" :key="index">
                    <el-row class="user" v-if="message.role == 'user'">
                        <el-col :span="22" :offset="1" class="user_content">
                            <mavon-editor class="user_content_span"
                                v-model="message.content"
                                :subfield="false" 
                                :defaultOpen="'preview'" 
                                :toolbarsFlag="false" 
                                :editable="false"/>
                        </el-col>
                        <el-col :span="1" class="user_head">
                            <img src="../../assets/img/logo.png">
                        </el-col>
                    </el-row>
                    <el-row v-if="message.role == 'user' && message.tokens">
                        <el-col :span="22" :offset="1" class="user_tokens">
                            <span>此问题消耗了 {{ message.tokens || 0 }} tokens</span>
                        </el-col>
                    </el-row>

                    <el-row class="bot" v-if="message.role == 'assistant'">
                        <el-col :span="1" class="bot_head">
                            <svg t="1683273862076" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2681">
                                <path d="M501.8 121.6h20.4v128h-20.4z" fill="#A0ABBD" p-id="2682"></path>
                                <path d="M512 873.5H226.5c-32.6 0-59.1-26.4-59.1-59.1V285.7c0-32.6 26.4-59.1 59.1-59.1H512v646.9z" fill="#6484BF" p-id="2683"></path>
                                <path d="M512 226.7h285.5c32.6 0 59.1 26.4 59.1 59.1v528.7c0 32.6-26.4 59.1-59.1 59.1H512V226.7z" fill="#4C6FAF" p-id="2684"></path>
                                <path d="M640.1 448.2m-59.1 0a59.1 59.1 0 1 0 118.2 0 59.1 59.1 0 1 0-118.2 0Z" fill="#FFFFFF" p-id="2685"></path>
                                <path d="M384.1 448.2m-59.1 0a59.1 59.1 0 1 0 118.2 0 59.1 59.1 0 1 0-118.2 0Z" fill="#FFFFFF" p-id="2686"></path>
                                <path d="M512 113.2m-49 0a49 49 0 1 0 98 0 49 49 0 1 0-98 0Z" fill="#A0ABBD" p-id="2687"></path>
                                <path d="M167.6 615.6l-54.4-27.2V458.1l54.4-29.2zM856.4 427.9l54.4 27.3v130.2l-54.4 29.2z" fill="#39507A" p-id="2688"></path>
                            </svg>
                        </el-col>
                        <el-col :span="22" class="bot_content">
                            <mavon-editor class="bot_content_span"
                                v-model="message.content"
                                :subfield="false" 
                                :defaultOpen="'preview'" 
                                :toolbarsFlag="false" 
                                :editable="false"
                                style="height: auto;"/>
                        </el-col>
                    </el-row>
                    <el-row v-if="message.role == 'assistant'">
                        <el-col :span="22" :offset="1" class="bot_tokens">
                            <span>此回答消耗了 {{ message.tokens || 0 }} tokens</span>
                        </el-col>
                    </el-row>
                </div>
            </div>
            <!-- 输入框 -->
            <div class="input" v-loading="loading"
                element-loading-text="AI 正在思考..."
                element-loading-spinner="el-icon-loading"
                element-loading-background="rgba(0, 0, 0, 0.8)"
            >
                <textarea id="input" v-model="newMessage" placeholder="请在此输入您的问题，输入完成后请点击左下角「发送」按钮进行发送，或者按`Shift`+`Enter`键进行发送"></textarea>
                <el-button class="send" type="pr" @click="sendMessage()">发送</el-button>
            </div>
        </el-col>
        <!-- prompt抽屉 -->
        <el-drawer
            title="Prompt 选择器"
            :visible.sync="promptSelectorDrawer"
            direction="rtl"
            :before-close="closePromptSelector"
            :modal="false">
            <PromptSelector :newMessage.sync="newMessage"></PromptSelector>
        </el-drawer>
    </el-row>
</template>

<script>
const PromptSelector = () => import("./promptSelector.vue");
export default {
    components: {
        PromptSelector
    },
    data() {
        let tips_arr = [
            "尊敬的用户，您好！欢迎使用`GPT-3.5`AI智能模型。\n \n", 
            "在使用过程中，请注意以下事项： \n",
            "1. 在体验过程中，请严格履行信息安全责任，确保您输入的内容符合社会主义核心价值观，不得含有颠覆国家政权、推翻社会主义制度、煽动分裂国家、破坏国家统一、宣扬恐怖主义、极端主义、宣扬民族仇恨、民族歧视、暴力、淫秽色情、虚假内容等信息，也不得含有扰乱经济秩序和社会秩序、侵害他人合法利益的内容。 \n",
            "2. 请您知悉，本服务提供的所有内容均由人工智能模型输出，因此可能存在错误或遗漏。我们并不保证输出内容的准确性、完整性和规范性，同时这些内容并不代表服务提供者的立场或观点。 \n",
            "3. AI会结合本聊天窗口的所有上下文对您的提问进行回答，所以每一个聊天窗口的问答越多，所消耗的tokens越多(`1000tokens ≈ 0.002$`)。为避免造成不必要的损失，如果您发送的问题与之前的问题没有关联，请点击左侧 **创建新聊天** 按钮新建窗口进行提问。 \n",
            "4. 开头输入 `/` 搜索并使用 Prompt 预设，这是一种可以赋予AI角色、使AI的回答更专业的技巧。 \n",
            "\n 接下来，请输入并发送您的第一个问题：",
        ];
        let tips = "";
        tips_arr.forEach(e=>{
            tips += e;
        })
        return {
            historyLoading: false,
            historys: [],
            historys_index: {},
            thisHistoryId: "",

            chatLoading: false,
            chatLoadingText: "",

            tips: tips,
            messages: [],
            newMessage: "",
            loading: false,

            promptSelectorDrawer: false,

        }
    },
    watch: {
        newMessage: {
            handler(value) {
                if(value === '/'){
                    this.promptSelectorDrawer = true;
                }else{
                    this.promptSelectorDrawer = false;
                }
            }
        }
    },
    mounted() {
        // 设置回车发送
        const input = document.querySelector('#input');
        input.addEventListener('keydown', (event) => {
            // 判断当前焦点是否在输入框内
            if (event.target === input) {
                // 判断按下的是否是Shift + 回车键
                let shiftKey = event.shiftKey
                if (shiftKey && event.keyCode === 13) {
                    event.returnValue = false;
                    // 执行方法
                    this.sendMessage();
                }
            }
        });

        this.toChatEnd();
        
        //拉取聊天记录
        this.getHistorys();
    },
    methods: {
        closePromptSelector(){
            this.promptSelectorDrawer = false;
        },
        sendMessage(){
            if(this.thisHistoryId === ""){
                this.$message.warning("请选择聊天后在发送消息");
                return;
            }

            let test = this.newMessage.replace(/\ /g, "");
            test = test.replace(/\r\n/g, "");
            test = test.replace(/\n/g, "");
            
            if(this.newMessage == "" || test == ""){
                this.$message.warning("请勿发送空内容");
                return;
            }
            this.messages.push({
                role: 'user',
                content: this.newMessage
            });
            // 等待DOM更新完成后滚动到底部
            this.$nextTick(() => {
                this.toChatEnd();
            })

            this.newMessage = "";
            this.loading = true;
            let vo = {
                historyId: this.thisHistoryId,
                chatMessages: this.messages
            }
            this.$api.ai.chat(vo).then(res=>{
                
                // 获取当前历史记录索引
                let index = this.historys_index[this.thisHistoryId];
                // 更新总消耗tokens数
                this.historys[index].totalTokens += res.data.totalTokens;
                // 更新历史记录名称
                if(res.data.historyName){
                    this.historys[index].historyName = res.data.historyName;
                }
                // 更新问题tokens
                this.messages[this.messages.length - 1].tokens = res.data.promptTokens;
                this.messages.push({
                    role: 'assistant',
                    content: res.data.content,
                    tokens: res.data.completionTokens
                })
                this.loading = false
                // 等待DOM更新完成后滚动到底部
                this.$nextTick(() => {
                    this.toChatEnd();
                })
            })
        },
        getMessages(historyId){
            this.chatLoading = true;
            this.chatLoadingText = "正在拉取聊天信息...";
            this.$api.ai.historyDetail(historyId).then(res=>{
                this.messages = res.data;
                this.chatLoading = false;
                // 等待DOM更新完成后滚动到底部
                this.$nextTick(() => {
                    this.toChatEnd();
                })
            })
        },
        getHistorys(){
            this.historyLoading = true;
            this.$api.ai.history().then(res=>{
                let historys = res.data;
                if(historys.length > 0){
                    this.historys = historys;
                    this.buildHistoryIndex();
                    this.chengeHistory(historys[0].uuid);
                }else{
                    this.newChat();
                }
                this.historyLoading = false;
            })
        },
        chengeHistory(uuid){
            if(this.thisHistoryId == uuid){
                return;
            }
            this.thisHistoryId = uuid;
            this.newMessage = "";
            this.getMessages(uuid);
        },
        newChat(){
            this.chatLoading = true;
            this.chatLoadingText = "正在创建新聊天...";
            this.$api.ai.createChat().then(res=>{
                if(res.code == 200){
                    let history = res.data;
                    this.historys.unshift(history);
                    this.buildHistoryIndex();
                    this.messages = [];
                    this.thisHistoryId = history.uuid;
                    this.newMessage = "";
                    this.$message.success("新聊天创建成功");
                }else{
                    this.$message.error(res.msg)
                }
                
                this.chatLoading = false;
            })
            this.$utils.sleep(300).then(res=>{
                this.messages = [];
                this.chatLoading = false;
                
            });  
        },
        buildHistoryIndex(){
            this.historys_index = {};
            this.historys.forEach((e, index)=>{
                this.historys_index[e.uuid] = index;
            })
        },
        // 定位聊天到末尾
        toChatEnd(){
            const messages = this.$refs.messages;
            messages.scrollTop = messages.scrollHeight;
        },
    }

}
</script>

<style lang="less" scoped>
.gpt_box {
    box-sizing: border-box;
    width: 100%;
    height: calc(100% - 60px);
    background-color: #f3f3f3;
    .historys {
        height: 100%;
        background-color: rgb(222,221,220);
        .new_chat_btn {
            box-sizing: border-box;
            margin: 5px 10px;
            height: 40px;
            line-height: 40px;
            text-align: center;
            border: 1px dashed white;
            border-radius: 10px;
            cursor: pointer;
        }
        .new_chat_btn:hover {
            border: 1px dashed #409EFF;
        }
        .title {
            display: block;
            height: 40px;
            box-sizing: border-box;
            padding: 10px 0 5px 0;
            margin: 0 10px 5px;
            text-align: center;
            border-bottom: 1px solid white;
            font-weight: 600;
            font-size: 18px;
        }
        .history_btn_box {
            box-sizing: border-box;
            height: calc(100% - 100px);
            overflow: auto;
            .hixtory_btn {
                margin: 5px 10px;
                height: 70px;
                text-align: left;
                padding: 0 5px;
                border: 1px dashed white;
                border-radius: 5px;
                cursor: pointer;
                .history_name{
                    height: 40px;
                    line-height: 40px;
                    white-space: nowrap;
                    overflow: hidden;
                    text-overflow:ellipsis;
                }
                .total_tokens {
                    font-size: 13px;
                    white-space: nowrap;
                    overflow: hidden;
                    text-overflow:ellipsis;
                }
            }
            .hixtory_btn:hover {
                border: 1px dashed #409EFF;
            }
            .this_history {
                border: 1px dashed #409EFF;
                background-color: #c4ddf5;
            }
        }
    }
    .chat{
        height: 100%;
        position: relative;
        .messages {
            box-sizing: border-box;
            padding: 20px;
            height: 70%;
            overflow: auto;
            .message{
                margin-bottom: 20px;
                .user {
                    .user_head{
                        img {
                            height: 40px;
                        }
                    }
                    .user_content {
                        .user_content_span {
                            height: auto;
                            min-height: auto;
                            font-size: 20px;
                            float: right;
                        }
                    }
                }
                .user_tokens {
                    text-align: right;
                    font-size: 12px;
                }
                .bot {
                    .bot_head {
                        text-align: right;
                        svg {
                            height: 40px;
                        }
                        
                    }
                    .bot_content {
                        .bot_content_span {
                            height: auto;
                            min-height: auto;
                            font-size: 20px;
                            float: left;
                        }
                    }
                }
                .bot_tokens {
                    display: inline-block;
                    padding: 0 10px;
                    font-size: 12px;
                }
            }
        }
        .input {
            box-sizing: border-box;
            width: 100%;
            height: 30%;
            padding: 20px 20px 70px;
            position: absolute;
            bottom: 0px;
            border-top: 1px solid #ccc;
            textarea {
                box-sizing: border-box;
                outline: none;
                border: none;
                width: 100%;
                height: 100%;
                resize: none;
                background-color: #f3f3f3;
                font-size: 16px;
                overflow-y: scroll;
            }
            .send{
                position: absolute;
                bottom: 20px;
                right: 20px;
            }
        }
    }

}
</style>